#-------------------------------------------------------------------------------
# Copyright (c) 2012 Huseyin BIYIK.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the GNU Public License v3.0
# which accompanies this distribution, and is available at
# http://www.gnu.org/licenses/gpl.html
# 
# Contributors:
#     Huseyin BIYIK - initial API and implementation
#-------------------------------------------------------------------------------
import threading, Queue, socket
from defs import *

debug = 3

class receive(threading.Thread):
	def __init__(self, laddr, lport):
		threading.Thread.__init__(self)
		self.q = Queue.Queue()
		self.lport = lport
		self.laddr = laddr
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
		self.sock.setblocking(1)
		self.sock.settimeout(1)
		self.isclosing = False
		self.islistenning = False
		self.sock.bind((self.laddr, self.lport))
		self.laddr, self.lport = self.sock.getsockname()
		if debug >= 3  : print "Network: listening on " + str((self.laddr, self.lport)) 
		self.start()

	def close(self):
		self.isclosing = True
		self.sock.close()
		threading.Thread.join(self)
		return True
	
	def get(self, block, timeout=0):
		try:
			return self.q.get(block, timeout)
		except Queue.Empty:
			if debug >= 5 : print "Network: No data is available"
			pass
		return None

	def run(self):
		while True:
			if self.isclosing:
				break
			data = None
			try:
				data, addr = self.sock.recvfrom(udp_packet_size) # buffer size is 1024 bytes
			except socket.error , e:
				if debug >= 5 : print "Network: Error occured  :" + str(e)

			if not data is None :
				if debug >= 4 : print "Network: Received message:" + str(data)
				self.q.put(data)

class transmit(threading.Thread):
	def __init__(self):
		threading.Thread.__init__(self)
		self.q = Queue.Queue()
		self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)			
		self.isclosing = False
		self.start()

	def close(self):
		self.sock.close()
		self.isclosing = True
		threading.Thread.join(self)
		return True

	def put(self, data, raddr, rport):
		self.q.put({'data':data, 'raddr':raddr, 'rport':rport})
		return True

	def run(self):
		while True:
			if self.isclosing:
				break
			else:
				try:
					data = self.q.get(True, 0)
					self.sock.sendto(data['data'], (data['raddr'], int(data['rport'])))
					if debug >= 4 : print "Network: Data sent to :" + data['raddr']
				except socket.error, e:
					if debug >= 5 : print "Network: Error occured  :" + str(e)
				except Queue.Empty, e:
					if debug >= 5 : print "Network: No data to get  :" + str(e)
